package com.vess.ratingweb;

import java.util.Date;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import javax.activation.CommandMap;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.activation.MailcapCommandMap;
import javax.mail.BodyPart;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;

public class Mail extends javax.mail.Authenticator
{
	private String username, password, fromAccount;
	
	private String[] toAccount;
	
	private String port, sport, host;
	
	private String subject, body;
	
	private boolean authen;
	
	private Multipart multipart;
	
	private MimeMessage message;
	
	private Context context;
	
	public Mail() 
	{
		host = "smtp.gmail.com";
		port = "465";
		sport = "465";
		
		username = "";
		password = "";
		fromAccount = "";
		subject = "";
		body = "";
		
		authen = true;
		
		multipart = new MimeMultipart();
		
		/*The CommandMap class provides an interface to a registry of command objects available in the system. 
		Developers are expected to either use the CommandMap implementation included with this package 
		(MailcapCommandMap) or develop their own. Note that some of the methods in this class are abstract.*/
		
		/*MailcapCommandMap extends the CommandMap abstract class. It implements a CommandMap whose configuration 
		is based on mailcap files (RFC 1524). The MailcapCommandMap can be configured both programmatically 
		and via configuration files.*/
		
		MailcapCommandMap mc = (MailcapCommandMap)CommandMap.getDefaultCommandMap();
		mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
		mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
		mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
		mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
		mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
		CommandMap.setDefaultCommandMap(mc);
	}

	public Mail(String username, String password, Context context)
	{
		this();
		this.username = username;
		this.password = password;
		this.context = context;
	}

	@Override
	protected PasswordAuthentication getPasswordAuthentication() 
	{
		return new PasswordAuthentication(username, password);
	}
	
	public boolean send()
	{
		Properties props = setProperties();
		
		/*The Session class represents a mail session and is not subclassed.
		It collects together properties and defaults used by the mail API's.
		A single default session can be shared by multiple applications on the desktop.
		Unshared sessions can also be created. The Session class provides access to the protocol providers 
		that implement the Store, Transport, and related classes.*/
		
		Session session = Session.getInstance(props, this);
		
		/*Class MimeMessage represents a MIME style email message. 
		It implements the Message abstract class and the MimePart interface.
		Clients wanting to create new MIME style messages will instantiate an empty MimeMessage object 
		and then fill it with appropriate attributes and content.*/
		
		message = new MimeMessage(session);
		
		sendMailThread send = new sendMailThread();
		send.execute();
		try {
			return send.get();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
		return false;
	}
	
	private Properties setProperties()
	{
		/*The Properties class represents a persistent set of properties. 
		The Properties can be saved to a stream or loaded from a stream. 
		Each key and its corresponding value in the property list is a string.
		A property list can contain another property list as its "defaults",
		this second property list is searched if the property key is not found in the original property list.*/
		Properties props = new Properties();
		
		props.put("mail.smtp.host", host);
		
		if (authen)
		{
			props.put("mail.smtp.auth", "true");
		}
		props.put("mail.smtp.port", port);
		props.put("mail.smtp.socketFactory.port", sport);
		props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
		props.put("mail.smtp.socketFactory.fallback", "false");
		
		return props;
	}
	
	public void attachFile(String filename, String namefile) throws MessagingException
	{
		BodyPart msgBodyPart = new MimeBodyPart();
		
		/*The DataSource interface provides the JavaBeans Activation Framework with an abstraction of an arbitrary 
		collection of data. It provides a type for that data as well as access to it in the form of InputStreams 
		and OutputStreams where appropriate.*/
		
		/*The FileDataSource class implements a simple DataSource object that encapsulates a file. 
		It provides data typing services via a FileTypeMap object.
		FileDataSource Typing Semantics
		The FileDataSource class delegates data typing of files to an object subclassed from the FileTypeMap class. 
		The setFileTypeMap method can be used to explicitly set the FileTypeMap for an instance of FileDataSource. 
		If no FileTypeMap is set, the FileDataSource will call the 
		FileTypeMap's getDefaultFileTypeMap method to get the System's default FileTypeMap.*/
		
		DataSource source = new FileDataSource(filename);
		
		/*The DataHandler class provides a consistent interface to data available in many different sources and formats. 
		It manages simple stream to string conversions and related operations using DataContentHandlers. 
		It provides access to commands that can operate on the data. The commands are found using a CommandMap.*/
		
		msgBodyPart.setDataHandler(new DataHandler(source));
		
		
		
		msgBodyPart.setFileName(namefile);
		
		multipart.addBodyPart(msgBodyPart);
	}
	
	public String getBody() 
	{
		return body;
	} 
 
	public String getSubject() 
	{
		return subject;
	} 
	
	public String[] getToAccount() 
	{
		return toAccount;
	} 
	
	public String getFromAccount() 
	{
		return fromAccount;
	} 
	
	public String getUsername() 
	{
		return username;
	} 
	
	public String getPassword() 
	{
		return password;
	} 
	
	public String getHost() 
	{
		return host;
	} 
	
	public void setBody(String body) 
	{
		this.body = body;
	} 
 
	public void setToAccount(String[] toAccount) 
	{
		this.toAccount = toAccount;
	}
 
	public void setFromAccount(String fromAccount) 
	{
		this.fromAccount = fromAccount;
	}
 
	public void setSubject(String subject) 
	{
		this.subject = subject;
	}
	
	public void setHost(String host) 
	{
		this.host = host;
	}
	
	class sendMailThread extends AsyncTask<String, Integer, Boolean>
	{
		@Override
		protected Boolean doInBackground(String... params) 
		{
			if (!username.equals("") && !password.equals("") && toAccount.length>0 && 
					!fromAccount.equals("") && !subject.equals("") && !body.equals(""))
			{			
				try 
				{
					/*Class InternetAddress represents an Internet email address using the syntax of RFC822. 
					Typical address syntax is of the form "user@host.domain" or "Personal Name <user@host.domain>".*/
					
					//add tai khoan nguoi gui
					message.setFrom(new InternetAddress(fromAccount));
					
					InternetAddress[] addressTo = new InternetAddress[toAccount.length];
					
					for (int i=0; i<toAccount.length; i++)
					{
						addressTo[i] = new InternetAddress(toAccount[i]);
					}
					
					//add cac tai khoan nguoi nhan
					message.setRecipients(MimeMessage.RecipientType.TO, addressTo);
					
					message.setSubject(subject);
					
					message.setSentDate(new Date());
					
					/*This class models a Part that is contained within a Multipart. 
					This is an abstract class. Subclasses provide actual implementations.
					BodyPart implements the Part interface. Thus, it contains a set of attributes and a "content".*/
					
					BodyPart msgBodyPart = new MimeBodyPart();
					
					msgBodyPart.setText(body);
					
					multipart.addBodyPart(msgBodyPart);
					
					message.setContent(multipart);
				
					Log.i("PreEnd", "OK");
					
					Transport.send(message);
			 		
					Log.i("End", "OK");
				} 
				catch (AddressException e) 
				{
					// TODO Auto-generated catch block
					e.printStackTrace();
				} 
				catch (MessagingException e) 
				{
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return true;
			}
			else
			{
				return false;
			}
		}

		@Override
		protected void onPostExecute(Boolean result) 
		{
			super.onPostExecute(result);
		}

	}
}
